package de.rayman2200.converter.plugin;

import java.awt.datatransfer.DataFlavor;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;

import de.rayman2200.converter.exception.ConverterException;


public class ToHex implements FileConverterPlugin
{

  private FileConfiguration fileConfig;

  @Override
  public boolean canHandle(DataFlavor df)
  {
    return df.isFlavorJavaFileListType() || df.isFlavorTextType();
  }

  @Override
  public void setFileConfiguration(FileConfiguration configuration)
  {
    fileConfig = configuration;
  }

  @Override
  public boolean performConvert(Object obj, DataFlavor df) throws ConverterException
  {
    if (df.isFlavorJavaFileListType())
    {
      if (obj instanceof List<?>)
      {
        List<File> files = (List<File>)obj;
        for ( File file : files )
        {
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          FileInputStream fis = null;
          try
          {
            fis = new FileInputStream(file);
            byte[] buffer = new byte[8 * 1024];
            int count = 0;
            while ((count = fis.read(buffer)) > 0)
            {
              baos.write(buffer, 0, count);
            }

            String hexBin = getHexString(baos.toByteArray());
            toOutput(hexBin);
          }
          catch (Exception e)
          {
            return false;
          }
          finally
          {
            if (fis != null)
            {
              try
              {
                fis.close();
              }
              catch (IOException e)
              {}
            }
          }
        }
        return true;
      }
    }
    else if (df.isFlavorTextType())
    {
      if (obj instanceof String)
      {
        String hexBin = getHexString(((String)obj).getBytes());
        // toOutput(outputType, hexBin);
      }
      else if (obj instanceof InputStreamReader)
      {
        try
        {
          InputStreamReader isr = (InputStreamReader)obj;
          char[] buffer = new char[124];
          int left = 0;
          StringBuilder sb = new StringBuilder();

          while ((left = isr.read(buffer)) > 0)
          {
            sb.append(buffer, 0, left);
          }
          String hexBin = getHexString(((String)obj).getBytes(""));
          // toOutput(outputType, hexBin);
        }
        catch (UnsupportedEncodingException e)
        {
          return false;
        }
        catch (IOException e)
        {
          return false;
        }

      }
    }

    return false;
  }

  private boolean toOutput(String content)
  {
    File output = fileConfig.createOutputFile();
    FileOutputStream fos = null;
    try
    {
      fos = new FileOutputStream(output);
      fos.write(content.getBytes());
    }
    catch (IOException e)
    {
      return false;
    }
    finally
    {
      if (fos != null)
      {
        try
        {
          fos.close();
        }
        catch (IOException e)
        {}
      }
    }
    return true;
  }

  private static final byte[] HEX_CHAR_TABLE = {(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4',
                                                (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9',
                                                (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e',
                                                (byte)'f'};

  private String getHexString(byte[] raw)
  {
    try
    {
      byte[] hex = new byte[2 * raw.length];
      int index = 0;

      for ( byte b : raw )
      {
        int v = b & 0xFF;
        hex[index++] = HEX_CHAR_TABLE[v >>> 4];
        hex[index++] = HEX_CHAR_TABLE[v & 0xF];
      }
      return new String(hex, "ASCII");
    }
    catch (UnsupportedEncodingException e)
    {
      return "";
    }
  }

  @Override
  public String toString()
  {
    return "ToHex";
  }
}
